﻿using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Brc_PaaS.Common.Helper
{
    public class RSAHelper
    {

        #region  加密
        /// <summary>
        /// RSA 加密
        /// </summary>
        /// <param name="dataToEncrypt">待加密数据</param>
        /// <param name="publicKey">公钥</param>
        /// <returns></returns>
        public static string Encrypt(string publicKey, string dataToEncrypt, string encoding = "UTF-8")
        {
            try
            {
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                Encoding encoder = Encoding.UTF8;
                byte[] data = encoder.GetBytes(dataToEncrypt);         //要加密的数据

                rsa.FromXmlString(publicKey);

                int keySize = rsa.KeySize / 8;

                int bufferSize = keySize - 11;

                byte[] buffer = new byte[bufferSize];

                MemoryStream msInput = new MemoryStream(data);

                MemoryStream msOuput = new MemoryStream();

                int readLen = msInput.Read(buffer, 0, bufferSize);

                while (readLen > 0)
                {
                    byte[] dataToEnc = new byte[readLen];
                    Array.Copy(buffer, 0, dataToEnc, 0, readLen);
                    byte[] encData = rsa.Encrypt(dataToEnc, false);
                    msOuput.Write(encData, 0, encData.Length);
                    readLen = msInput.Read(buffer, 0, bufferSize);
                }

                msInput.Close();
                byte[] result = msOuput.ToArray();    //得到加密结果

                msOuput.Close();
                rsa.Clear();
                return Convert.ToBase64String(result);
            }
            catch
            {
                return "";
            }

        }

        #endregion

        #region 解密
        /// <summary>
        /// RSA 解密
        /// </summary>
        /// <param name="encryptedData">待解密数据</param>
        /// <param name="privateKey">私钥</param>
        /// <returns></returns>
        public static string Decrypt(string privateKey, string encryptedData, string encoding = "UTF-8")
        {
            try
            {
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                Encoding encoder = Encoding.UTF8;
                byte[] dataEnc = Convert.FromBase64String(encryptedData);//加载密文

                rsa.FromXmlString(privateKey);

                int keySize = rsa.KeySize / 8;

                byte[] buffer = new byte[keySize];

                MemoryStream msInput = new MemoryStream(dataEnc);

                MemoryStream msOuput = new MemoryStream();

                int readLen = msInput.Read(buffer, 0, keySize);

                while (readLen > 0)
                {

                    byte[] dataToDec = new byte[readLen];

                    Array.Copy(buffer, 0, dataToDec, 0, readLen);

                    byte[] decData = rsa.Decrypt(dataToDec, false);

                    msOuput.Write(decData, 0, decData.Length);

                    readLen = msInput.Read(buffer, 0, keySize);

                }

                msInput.Close();

                byte[] result = msOuput.ToArray();    //得到解密结果

                msOuput.Close();

                rsa.Clear();

                return Encoding.GetEncoding(encoding).GetString(result);
            }
            catch
            {
                return "";
            }
        }
        #endregion


        #region 加签

        /// <summary>
        /// RSA签名
        /// </summary>
        /// <param name="privateKey">私钥</param>
        /// <param name="data">待签名的内容</param>
        /// <returns></returns>
        public static string RSASign(string data, string privateKey)
        {
            var signer = SignerUtilities.GetSigner("SHA1withRSA");
            var privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(StrToToHexByte(privateKey));
            signer.Init(true, privateKeyParam);
            var plainBytes = Encoding.UTF8.GetBytes(data);
            signer.BlockUpdate(plainBytes, 0, plainBytes.Length);
            var signBytes = signer.GenerateSignature();
            return ByteToHexStr(signBytes);

        }

        #endregion

        #region 验签       

        /// <summary> 
        /// 验证签名
        /// </summary>
        /// <param name="data"></param>
        /// <param name="signature"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static bool VerifyCSharp(string data, string publicKey, string signature)
        {
            try
            {
                var signer = SignerUtilities.GetSigner("SHA1withRSA");
                var publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(StrToToHexByte(publicKey));
                signer.Init(false, publicKeyParam);
                var signBytes = StrToToHexByte(signature);
                var plainBytes = Encoding.UTF8.GetBytes(data);
                signer.BlockUpdate(plainBytes, 0, plainBytes.Length);
                var ret = signer.VerifySignature(signBytes);
                return ret;
            }
            catch (Exception ex)
            {
                return false;
            }

        }

        /// <summary>
        /// 生成密匙对
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static KeyValuePair<string, string> GetPairKey(string token)
        {
            var generator = new RsaKeyPairGenerator();
            var seed = Encoding.UTF8.GetBytes(token);
            var secureRandom = new SecureRandom();
            secureRandom.SetSeed(seed);
            generator.Init(new KeyGenerationParameters(secureRandom, 4096));
            var pair = generator.GenerateKeyPair();
            var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(pair.Private);
            var serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetDerEncoded();
            //var serializedPrivate = Convert.ToBase64String(serializedPrivateBytes);
            var serializedPrivate = ByteToHexStr(serializedPrivateBytes);

            var publickKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pair.Public);
            var serializedPublicBytes = publickKeyInfo.ToAsn1Object().GetDerEncoded();
            //var serializedPublic = Convert.ToBase64String(serializedPublicBytes);
            var serializedPublic = ByteToHexStr(serializedPublicBytes);


            var dic = new KeyValuePair<string, string>(serializedPublic, serializedPrivate);
            return dic;
        }
        /// <summary>
        /// 字符串转16进制字节数组
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        private static byte[] StrToToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }
        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string ByteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    returnStr += bytes[i].ToString("X2");
                }
            }
            return returnStr;
        }


        #endregion
    }
}
